package edu.whut.mall.common.util;

import org.apache.http.ssl.SSLContexts;
import org.apache.log4j.Logger;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Map;

/**
 * @author shuxibing
 * @date 2019/10/9 9:34
 * @uint d9lab
 * @Description: 仅仅只支付的api，不涉及商户账号的各种配置证书和密码
 */
public class WxPayApi {
    private static Logger log = Logger.getLogger(WxPayApi.class);

    /**
     * 统一下单接口
     */
    private static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    /**
     * 关闭订单
     */
    private static final String CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder";
    /**
     * 订单查询
     */
    private static final String ORDER_QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * app申请退款
     */
    public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
    /**
     * app查询退款
     */
    public static final String REFUND_QUERY_URL = "https://api.mch.weixin.qq.com/pay/refundquery";

    /**
     * 企业付款到零钱
     */
    private static final String TRANSFERS_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
    /**
     * 查询企业付款零钱
     */
    private static final String GET_TRANSFER_INFO_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
    /**
     * 企业付款到银行
     */
    private static final String PAY_BANK_URL = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
    /**
     * 查询企业付款到银行
     */
    private static final String QUERY_BANK_URL = "https://api.mch.weixin.qq.com/mmpaysptrans/query_bank";
    /**
     * 下载资金对账单
     */
    private static final String DOWNLOAD_BILLY_URL = "https://api.mch.weixin.qq.com/pay/downloadbill";

    /**
     * 统一下单
     *
     * @param params    统一下单请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String pushOrder( Map<String, String> params) throws Exception {
        return WxPayApi.doPost(UNIFIED_ORDER_URL, params);
    }


    /**
     *
     *
     * @param params    关闭订单
     * @return {@link String} 请求返回的结果
     */
    public static String closeOrder( Map<String, String> params) throws Exception {
        return WxPayApi.doPost(CLOSE_ORDER_URL, params);
    }

    /**
     * 订单查询
     *
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String orderQuery(Map<String, String> params) throws Exception {
        return WxPayApi.doPost(ORDER_QUERY_URL, params);
    }

    /**
     * 申请退款
     * @param params
     * @param certPath
     * @param certPassword  商户的mch_id
     * @return
     * @throws Exception
     */
    public static String orderRefund( Map<String, String> params,String certPath,String certPassword ) throws Exception {
        return WxPayApi.doPostSSL(REFUND_URL, params,certPath,certPassword);
    }

    /**
     * 申请退款
     * @param params
     * @param certFile
     * @param certPassword
     * @return
     * @throws Exception
     */
    public static String orderRefund( Map<String, String> params,InputStream certFile,String certPassword ) throws Exception {
        return WxPayApi.doPostSSL(REFUND_URL, params,certFile,certPassword);
    }

    /**
     * 查询退款
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String orderRefundQuery(Map<String, String> params) throws Exception{
        return WxPayApi.doPost(REFUND_QUERY_URL, params);
    }

    /**
     * 企业付款到零钱
     *
     * @param params       请求参数
     * @param certPath     证书文件目录
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String transfers(Map<String, String> params, String certPath, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(TRANSFERS_URL, params, certPath, certPassword);
    }

    /**
     * 企业付款到零钱
     *
     * @param params       请求参数
     * @param certFile     证书文件的 InputStream
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String transfers(Map<String, String> params, InputStream certFile, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(TRANSFERS_URL, params, certFile, certPassword);
    }

    /**
     * 查询企业付款到零钱
     *
     * @param params       请求参数
     * @param certPath     证书文件目录
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String getTransferInfo(Map<String, String> params, String certPath, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(GET_TRANSFER_INFO_URL, params, certPath, certPassword);
    }

    /**
     * 查询企业付款到零钱
     *
     * @param params       请求参数
     * @param certFile     证书文件的 InputStream
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String getTransferInfo(Map<String, String> params, InputStream certFile, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(GET_TRANSFER_INFO_URL, params, certFile, certPassword);
    }

    /**
     * 企业付款到银行
     *
     * @param params       请求参数
     * @param certPath     证书文件目录
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String payBank(Map<String, String> params, String certPath, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(PAY_BANK_URL, params, certPath, certPassword);
    }

    /**
     * 企业付款到银行
     *
     * @param params       请求参数
     * @param certFile     证书文件的 InputStream
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String payBank(Map<String, String> params, InputStream certFile, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(PAY_BANK_URL, params, certFile, certPassword);
    }

    /**
     * 查询企业付款到银行
     *
     * @param params       请求参数
     * @param certPath     证书文件目录
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String queryBank(Map<String, String> params, String certPath, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(QUERY_BANK_URL, params, certPath, certPassword);
    }

    /**
     * 查询企业付款到银行
     *
     * @param params       请求参数
     * @param certFile     证书文件的  InputStream
     * @param certPassword 证书密码
     * @return {@link String} 请求返回的结果
     */
    public static String queryBank(Map<String, String> params, InputStream certFile, String certPassword) throws Exception {
        return WxPayApi.doPostSSL(QUERY_BANK_URL, params, certFile, certPassword);
    }

    /**
     * 下载对账单
     *
     * @param params    请求参数
     * @return {@link String} 请求返回的结果
     */
    public static String downloadBill(Map<String, String> params) throws Exception {
        return WxPayApi.doPost(DOWNLOAD_BILLY_URL,params);
    }



    public static String doPost(String url, Map<String, String> params) throws Exception {
        return HttpUtil.httpsRequest(url,"POST",WxPayKit.toXml(params)).toString();
    }

    public static String doPostSSL(String url, Map<String, String> params,String certPath,String certPass) throws Exception{
        SSLSocketFactory sslSocketFactory = getSSLSocketFactory(certPass, certPath, null);
        return HttpUtil.httpsRequest(url, "POST", WxPayKit.toXml(params),sslSocketFactory).toString();
    }
    public static String doPostSSL(String url, Map<String, String> params,InputStream certFile,String certPass) throws Exception{
        SSLSocketFactory sslSocketFactory = getSSLSocketFactory(certPass, null, certFile);
        return HttpUtil.httpsRequest(url, "POST", WxPayKit.toXml(params),sslSocketFactory).toString();
    }


    /**
     * ssl加密证书
     * @return
     * @throws Exception
     */
    private static SSLSocketFactory getSSLSocketFactory(String certPass, String certPath, InputStream certFile) throws Exception{

        //指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        InputStream ins=null;
        try {
            if (certFile != null) {
                keyStore.load(certFile, certPass.toCharArray());
            } else {
                //读取配置文件
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                ins = classLoader.getResourceAsStream(certPath);
                keyStore.load(ins, certPass.toCharArray());
            }
        }catch (Exception e){
            log.error("证书出错");
            log.error(e.getMessage(), e);
        }finally {
            ins.close();
        }
        SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, certPass.toCharArray()).build();
//        //指定TLS版本
//        SSLSocketFactory sslsf = new SSLSocketFactory(sslContext, new String[] {"TLSv1"},null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        SSLSocketFactory sslsf = sslContext.getSocketFactory();
        return sslsf;
    }

}